﻿/**
 * Created by xjchen on 6/25/21.
 * */

#ifndef MIDDLEWARE_PARAMETERS_H
#define MIDDLEWARE_PARAMETERS_H


#include "Header.h"
#include <complex>
#include <vector>
#include <unordered_map>
#include "DeviceReader.h"
#include "TaskModule.h"
#include "Application.h"

/**
 * 获取或设置参数的控制指令除了能识别注册的的自定义结构体外，还能识别以下基本数据类型(其中SIZE为数组长度，为一整数值)：
  "bool"                   -> bool
  "int"                    -> int
  "int [SIZE]"             -> int [SIZE]
  "float"                  -> float
  "float [SIZE]"           -> float [SIZE]
  "double"                 -> double
  "double [SIZE]"          -> double [SIZE]
  "complex<float>"         -> std::complex<float>
  "complex<float> [SIZE]"  -> std::complex<float> [SIZE]
  "complex<double>"        -> std::complex<double>
  "complex<double> [SIZE]" -> std::complex<double> [SIZE]
  "string"                 -> std::string
 **/


struct parameter_header {
    bool is_struct = false;
    bool is_modified = false;
    int index_in_array = 0;
    std::string field;  /*参数实例名称*/
    std::string type;  /*自定义结构体类型或者上述的基本数据类型*/
    int size;
};

extern Parameters *globalParametersInstance;    /** Ti6678 通过全局变量使得主从核同步 */
extern void registerGlobalParameter(std::string field, parameter_header *addr);

template<typename T>
struct parameter_info {
    parameter_header header;
    T value;
    T lastValue;

    parameter_info(bool is_struct, std::string field, std::string type, T value) {
        this->header.is_struct = is_struct;
        this->header.field = field;
        this->header.type = type;
        this->header.size = sizeof(T);
        this->value = value;
        this->lastValue = value;
        registerGlobalParameter(field, &header);
    }
};

#define DECLARE_SETTERS_AND_GETTERS(_type, field) \
void set_parameter_ ## field(_type value,TaskModule *pModule){\
    updateValue(reinterpret_cast<parameter_header*>(&field),&value,0,-1,pModule);}\
void set_parameter_ ## field(_type value,int delay,int timeout,TaskModule *pModule){\
    updateValue(reinterpret_cast<parameter_header*>(&field),&value,delay,timeout,pModule);}\
_type get_parameter_ ## field(TaskModule *pModule){\
return reinterpret_cast<_type*>(getValue(reinterpret_cast<parameter_header*>(&field),pModule))[0];}

#define add_parameter(_type, field, default_value) public: parameter_info<_type> field{false,#field,#_type,default_value};\
DECLARE_SETTERS_AND_GETTERS(_type, field)

#define add_struct_parameter(_struct, field) public: parameter_info<_struct> field{true,#field,#_struct,_struct{}};\
DECLARE_SETTERS_AND_GETTERS(_struct, field)

class Parameters {
public:
    void *getValue(parameter_header *addr, TaskModule *pModule);

    parameter_header *findParameter(std::string field);

    void updateValue(parameter_header *addr, void *value, int delay, int timeout, TaskModule *pModule);

    std::unordered_map<std::string, parameter_header *> &getAllParameters();

private:
    friend class Application;

    void addReferenceReaders(std::vector<DeviceReader *> readers);

    void setValueCapacity(int capacity);

    void allocMemories();
};


#endif /** MIDDLEWARE_PARAMETERS_H*/
